package genedit.model;

import genedit.controller.SelectionState;
import genedit.controller.State;
import genedit.gui.GProjectTree;
import genedit.view.graph.GraphDocumentView;
import genedit.view.graph.GraphWorkArea;

import java.io.File;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import javax.swing.SwingUtilities;
import javax.swing.tree.TreeNode;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * Ova klasa predstavlja koren stabla hijerarhije.
 * 
 * @author Nikola Luburić
 * @version 1.2 18/12/13
 */
public class Workspace extends HierarchyElement {
	private static final long serialVersionUID = 1L;

	private XStream xstream;

	/**
	 * Dokument koji je trenutno u fokusu.
	 */
	private GraphDocumentView activeDocument;

	/**
	 * Lokacija workspace-a; Direktorijum u kom je smešten.
	 */
	private File path;

	/**
	 * Singleton instanca workspace-a
	 */
	private static Workspace instance = null;

	/**
	 * Referenca na klasu zadužena za rad sa selekcijom u hijerarhiji.
	 */
	private HierarchySelection treeSelection;

	/**
	 * Lista trenutno otvorenih dokumenata.
	 */
	private List<Project> projects;

	/**
	 * Aktivno stanje koje se prenosi na naredni izabran dokument. Ako se
	 * izabere stanje dodavanja pravougaonika, i zatim se pređe na drugi (već
	 * otvoren ili novootvoren dokument) njegovo trenutno stanje će biti
	 * postavljeno na dodavanje pravougaonika.
	 */
	private State activeState;

	public static Workspace getInstance() {
		if (instance == null)
			instance = new Workspace();
		return instance;
	}

	public File getPath() {
		return path;
	}

	public void setPath(File path) {
		this.path = path;
	}

	public void rename(String name) {
	}

	public GraphDocumentView getActiveDocument() {
		return activeDocument;
	}

	public void setActiveDocument(GraphDocumentView newDocument) {
		this.activeDocument = newDocument;
		State activeState = getActiveState();
		GraphWorkArea graphWorkArea = (GraphWorkArea) this.activeDocument.getWorkArea();
		activeState.setContext(graphWorkArea);
		graphWorkArea.getController().setCurrentState(activeState);

	}

	private Workspace() {
		projects = new java.util.ArrayList<Project>();
		activeState = new SelectionState(null);
	}

	public String toString() {
		return "Workspace";
	}

	public HierarchySelection getTreeSelection() {
		return treeSelection;
	}

	public void setTreeSelection(HierarchySelection newHierarchySelection) {
		this.treeSelection = newHierarchySelection;
	}

	public List<Project> getProjects() {
		if (projects == null)
			projects = new java.util.ArrayList<Project>();
		return projects;
	}

	public java.util.Iterator<Project> getIteratorProjects() {
		if (projects == null)
			projects = new java.util.ArrayList<Project>();
		return projects.iterator();
	}

	public void setProjects(java.util.Collection<Project> newProjects) {
		removeAllProjects();
		for (java.util.Iterator<Project> iter = newProjects.iterator(); iter.hasNext();)
			addProjects((Project) iter.next());
	}

	public void addProjects(Project newProject) {
		if (newProject == null)
			return;
		boolean alreadyExists = false;
		for (Project project : projects) {
			if (project.getName().equals(newProject)) {
				alreadyExists = true;
				break;
			}
		}
		if (this.projects == null)
			this.projects = new java.util.ArrayList<Project>();
		if (!this.projects.contains(newProject) && !alreadyExists)
			this.projects.add(newProject);
		SwingUtilities.updateComponentTreeUI(GProjectTree.getInstance().getTree());
	}

	public void removeProjects(Project oldProject) {
		if (oldProject == null)
			return;
		if (this.projects != null)
			if (this.projects.contains(oldProject))
				this.projects.remove(oldProject);
		SwingUtilities.updateComponentTreeUI(GProjectTree.getInstance().getTree());
	}

	public void removeAllProjects() {
		if (projects != null)
			projects.clear();
		SwingUtilities.updateComponentTreeUI(GProjectTree.getInstance().getTree());
	}

	@Override
	public TreeNode getChildAt(int childIndex) {
		return projects.get(childIndex);
	}

	@Override
	public int getChildCount() {
		return projects.size();
	}

	@Override
	public int getIndex(TreeNode node) {
		return projects.indexOf(node);
	}

	@Override
	public boolean getAllowsChildren() {
		return true;
	}

	@Override
	public boolean isLeaf() {
		return false;
	}

	@SuppressWarnings("rawtypes")
	@Override
	public Enumeration children() {
		return Collections.enumeration(projects);
	}

	@Override
	public TreeNode getParent() {
		return null;
	}

	public State getActiveState() {
		return activeState;
	}

	public void setActiveState(State activeState) {
		this.activeState = activeState;
	}

	public XStream getXstream() {
		if (xstream == null)
			xstream = new XStream(new DomDriver());
		return xstream;
	}

	public void setXstream(XStream xstream) {
		this.xstream = xstream;
	}

	@Override
	public boolean isSaved() {
		return false;
	}

	@Override
	public void setSaved(boolean saved) {
	}
}